#include "CPlayer.h"
#include "..\Wrappers\CSGD_DirectInput.h"
#include "..\Wrappers\CSGD_Direct3D.h"
#include "..\Messaging\CSGP_MessageSystem.h"
#include "..\CCyberSpaceState.h"
#include "CPistolBullet.h"
#include "CShotgunBullet.h"
#include "CDrop.h"
#include "..\CPrintBitmapToScreen.h"
#include "CWorm.h"
#include "CSpider.h"
#include "..\Firewall.h"
#include "CNode.h"
#include "..\CTile.h"
#include "..\\CAnimationManager.h"
#include "..\CLayer.h"
#include "..\CGame.h"
#include "..\CSpaceStationState.h"
#include "..\COptionsState.h"
#include "..\CDoor.h"

CPlayer::CPlayer(void)
{
	// Temporary sets for display
	SetWidth(43);
	SetHeight(60);
	SetSpeedFactor(0.0f);

	m_nPistolClip = 1;
	m_nShotgunClip = 0;
	m_nRocketClip = 0;
	m_nExGrenadeClip = 1;
	m_nFWGrenadeClip = 1;

	m_fFireTimer = 0.0f;
	m_fShotTimer = 0.0f;
	m_fRocketTimer = 0.0f;

	// Initialize the flash timer
	m_fFlashTimer = 0.0f;

	// Initialize upgrades
	m_bSpeedActive = false;
	m_bFireRateActive = false;

	// Load assets 
	m_nPistolID = CSGD_FModManager::GetInstance()->LoadSound("Resource/Sound/SGP_PistolShot.wav");
	m_nShotgunID = CSGD_FModManager::GetInstance()->LoadSound("Resource/Sound/SGP_ShotgunShot.wav");
	m_nRocketID = CSGD_FModManager::GetInstance()->LoadSound("Resource/Sound/SGP_RocketFire.wav");
	m_nEmptyID = CSGD_FModManager::GetInstance()->LoadSound("Resource/Sound/SGP_GunDry.wav");
	m_nThrowID = CSGD_FModManager::GetInstance()->LoadSound("Resource/Sound/SGP_GrenadeThrow.wav");
	//CursorID =CSGD_TextureManager::GetInstance()->LoadTexture("Resource/Graphics/Reticle.png", D3DCOLOR_XRGB(255,0,255));

	// Set volume
	CSGD_FModManager::GetInstance()->SetVolume(m_nEmptyID, COptionsState::GetInstance()->GetSFXVolume());
	CSGD_FModManager::GetInstance()->SetVolume(m_nThrowID, COptionsState::GetInstance()->GetSFXVolume());
}

CPlayer::~CPlayer(void)
{
	
}

CPlayer* CPlayer::GetInstance(void)
{
	static CPlayer instance;
	return &instance;
}

void CPlayer::Update(float fElapsedTime)
{
	CBase::Update(fElapsedTime);
	
	
	m_tToMouse.fX = float(CSGD_DirectInput::GetInstance()->MouseGetPosX() + CCamera::GetInstance()->GetOffsetX());
	m_tToMouse.fY = float(CSGD_DirectInput::GetInstance()->MouseGetPosY() + CCamera::GetInstance()->GetOffsetY());

	m_tStartPos.fX = GetPosX();
	m_tStartPos.fY = GetPosY();
	
	// Adjust the volume
	CSGD_FModManager::GetInstance()->SetVolume(m_nPistolID, COptionsState::GetInstance()->GetSFXVolume());
	CSGD_FModManager::GetInstance()->SetVolume(m_nShotgunID, COptionsState::GetInstance()->GetSFXVolume());
	CSGD_FModManager::GetInstance()->SetVolume(m_nRocketID, COptionsState::GetInstance()->GetSFXVolume());

	// Update the fire timers
	m_fFireTimer += fElapsedTime; // Pistol timer
	m_fShotTimer += fElapsedTime; // Shotgun timer
	m_fRocketTimer += fElapsedTime; // Rocket timer

	// Is the screen flashing? Update the timer
	if(m_bIsFlashing)
	{
		m_fFlashTimer += fElapsedTime;
		if(m_fFlashTimer > 0.1f)
		{
			m_bIsFlashing = false;
			m_fFlashTimer = 0.0f;
		}
	}

	// Use grenades
	if(CSGD_DirectInput::GetInstance()->KeyPressed(DIK_G) || CSGD_DirectInput::GetInstance()->JoystickButtonPressed(5))
	{
		if(CCyberSpaceState::GetInstance()->GetCurrentGrenade() == CCyberSpaceState::EX_GRENADE)
		{
			if(GetExGrenades() > 0)
			{
					CPlayer::GetInstance()->SetExGrenades(CPlayer::GetInstance()->GetExGrenades() - 1);
					CSGD_FModManager::GetInstance()->PlaySoundA(m_nThrowID);
					CSGP_MessageSystem::GetInstance()->SendMessage(new CCreateExGrenadeMessage(this));	
			}
		}
		if(CCyberSpaceState::GetInstance()->GetCurrentGrenade() == CCyberSpaceState::FW_GRENADE)
		{
			if(GetFwGrenades() > 0)
			{
					CPlayer::GetInstance()->SetFwGrenades(CPlayer::GetInstance()->GetFwGrenades() - 1);
					CSGD_FModManager::GetInstance()->PlaySoundA(m_nThrowID);
					CSGP_MessageSystem::GetInstance()->SendMessage(new CCreateFwGrenadeMessage(this));
			}
		}
	}

	// Fire weapon
	if(CSGD_DirectInput::GetInstance()->MouseButtonDown(0) || CSGD_DirectInput::GetInstance()->JoystickButtonDown(2))
	{
		if(CCyberSpaceState::GetInstance()->GetCurrentWeapon() == CCyberSpaceState::PISTOL)
		{ // If the pistol is selected, shoot pistol bullets

			if(GetPistolAmmo() > 0) // If the player still has ammo, shoot the pistol
			{
				if(GetFireRateActive())
				{
					if(m_fFireTimer > 0.2f)
					{
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nPistolID);
						CPlayer::GetInstance()->SetPistolAmmo(CPlayer::GetInstance()->GetPistolAmmo() - 1);
						CSGP_MessageSystem::GetInstance()->SendMessage(new CCreatePlayerBulletMessage(this, CPistolBullet::BLT_PLAYER));
						m_fFireTimer = 0.0f;
					}
				}
				else
				{
					if(m_fFireTimer > 0.7f)
					{
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nPistolID);
						CPlayer::GetInstance()->SetPistolAmmo(CPlayer::GetInstance()->GetPistolAmmo() - 1);
						CSGP_MessageSystem::GetInstance()->SendMessage(new CCreatePlayerBulletMessage(this, CPistolBullet::BLT_PLAYER));
						m_fFireTimer = 0.0f;
					}
				}
			}
			else
			{
				if(CGame::GetInstance()->GetStates().back() == CCyberSpaceState::GetInstance())
				{
					if(!CSGD_FModManager::GetInstance()->IsSoundPlaying(m_nEmptyID))
					CSGD_FModManager::GetInstance()->PlaySoundA(m_nEmptyID);
				}
			}
		}
		else if(CCyberSpaceState::GetInstance()->GetCurrentWeapon() == CCyberSpaceState::SHOTGUN)
		{ // If the shotgun is selected, shoot shotgun bullets
			
			if(GetShotgunAmmo() > 0)
			{
				if(GetFireRateActive())
				{
					if(m_fShotTimer > 0.5f)
					{
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nShotgunID);
						CPlayer::GetInstance()->SetShotgunAmmo(CPlayer::GetInstance()->GetShotgunAmmo() - 1);
						for(unsigned int i=0; i<5; ++i)
							CSGP_MessageSystem::GetInstance()->SendMessage(new CCreateShotgunBulletMessage(this));

						m_fShotTimer = 0.0f;
					}
				}
				else
				{
					if(m_fShotTimer > 1.0f)
					{
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nShotgunID);
						CPlayer::GetInstance()->SetShotgunAmmo(CPlayer::GetInstance()->GetShotgunAmmo() - 1);
						for(unsigned int i=0; i<5; ++i)
							CSGP_MessageSystem::GetInstance()->SendMessage(new CCreateShotgunBulletMessage(this));

						m_fShotTimer = 0.0f;
					}
				}
			}
			else
			{
				if(CGame::GetInstance()->GetStates().back() == CCyberSpaceState::GetInstance())
				{
					if(!CSGD_FModManager::GetInstance()->IsSoundPlaying(m_nEmptyID))
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nEmptyID);
				}
			}
		}
		else if(CCyberSpaceState::GetInstance()->GetCurrentWeapon() == CCyberSpaceState::ROCKETS)
		{ // If the rocket launcher is selected, shoot rockets
			if(GetRocketAmmo() > 0)
			{
				if(GetFireRateActive())
				{
					if(m_fRocketTimer > 1.0f)
					{
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nRocketID);
						CPlayer::GetInstance()->SetRocketAmmo(CPlayer::GetInstance()->GetRocketAmmo() - 1);
						CSGP_MessageSystem::GetInstance()->SendMessage(new CCreateRocketBulletMessage(this));
						m_fRocketTimer = 0.0f;
					}
				}
				else
				{
					if(m_fRocketTimer > 1.5f)
					{
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nRocketID);
						CPlayer::GetInstance()->SetRocketAmmo(CPlayer::GetInstance()->GetRocketAmmo() - 1);
						CSGP_MessageSystem::GetInstance()->SendMessage(new CCreateRocketBulletMessage(this));
						m_fRocketTimer = 0.0f;
					}
				}
				
			}
			else
			{
				if(CGame::GetInstance()->GetStates().back() == CCyberSpaceState::GetInstance())
				{
					if(!CSGD_FModManager::GetInstance()->IsSoundPlaying(m_nEmptyID))
						CSGD_FModManager::GetInstance()->PlaySoundA(m_nEmptyID);
				}
			}
		}
	}



	CNode* node;
	if(CSpaceStationState::GetInstance()->getstate())
	{
		node = CSpaceStationState::GetInstance()->getnode();
	}
	else
	{
		node = CCyberSpaceState::GetInstance()->getnode();

	}
	if(node)
	{
		RECT obj = this->GetCollisionRect();
		std::vector<CLayer*>* layers = node->getlayers();
		if(CSpaceStationState::GetInstance()->getstate())
		{
			vector<CDoor*>* doors = node->getdoors();
			for(unsigned int i = 0; i < (*doors).size();i++)
			{
				RECT temp;
				if(!(*doors)[i]->getopen())
				{
					RECT curtile = (*doors)[i]->GetRect();
					if(IntersectRect(&temp, &obj, &curtile))
					{
						int wid = temp.right - temp.left;
						int het = temp.bottom - temp.top;

						if(wid > het)
						{
							if(obj.bottom > curtile.top && obj.top < curtile.top)
							{
								SetPosY(GetPosY() - (obj.bottom - curtile.top));
								SetVelY(0.0f);
							}
							if(obj.top < curtile.bottom && obj.bottom > curtile.bottom)
							{
								SetPosY(GetPosY() - (obj.top - curtile.bottom));
								SetVelY(0.0f);
							}

						}
						else if(het > wid)
						{
							if(obj.right > curtile.left && obj.left < curtile.left && GetVelX() != 0)
							{
								SetPosX(GetPosX() - (obj.right - curtile.left));
								SetVelX(0.0f);
							}

							if(obj.left < curtile.right && obj.right > curtile.right && GetVelX() != 0)
							{
								SetPosX(GetPosX() - (obj.left - curtile.right));
								SetVelX(0.0f);
							}
						}
					}
				}
			}
		}
		for(unsigned int i = 1; i < (*layers).size(); i++)
		{
			std::vector<CTile*>* tiles = (*layers)[i]->GetTiles();
			for(unsigned int j = 0; j < tiles->size(); j++)
			{
				RECT curtile;
				RECT temp;
				curtile.left = tiles->operator[](j)->GetmX() * tiles->operator[](j)->GetWidth();
				curtile.top = tiles->operator[](j)->GetmY() * tiles->operator[](j)->GetHeight();
				curtile.bottom = curtile.top + tiles->operator[](j)->GetHeight();
				curtile.right = curtile.left + tiles->operator[](j)->GetWidth();

				if(IntersectRect(&temp, &obj, &curtile))
				{


					int wid = temp.right - temp.left;
					int het = temp.bottom - temp.top;

					if(wid > het)
					{
						if(obj.bottom > curtile.top && obj.top < curtile.top)
						{
							SetPosY(GetPosY() - (obj.bottom - curtile.top));
							SetVelY(0.0f);
						}
						if(obj.top < curtile.bottom && obj.bottom > curtile.bottom)
						{
							SetPosY(GetPosY() - (obj.top - curtile.bottom));
							SetVelY(0.0f);
						}

					}
					else if(het > wid)
					{
						if(obj.right > curtile.left && obj.left < curtile.left && GetVelX() != 0)
						{
							SetPosX(GetPosX() - (obj.right - curtile.left));
							SetVelX(0.0f);
						}

						if(obj.left < curtile.right && obj.right > curtile.right && GetVelX() != 0)
						{
							SetPosX(GetPosX() - (obj.left - curtile.right));
							SetVelX(0.0f);
						}
					}
					else
					{

					}
				}
			}
		}
		
	}

}
void CPlayer::Render(void)
{
	// Show collison box
	RECT drawRect = GetCollisionRect();
	drawRect.top -= CCamera::GetInstance()->GetOffsetY();
	drawRect.bottom -= CCamera::GetInstance()->GetOffsetY();
	drawRect.left -= CCamera::GetInstance()->GetOffsetX();
	drawRect.right -= CCamera::GetInstance()->GetOffsetX();

	if(m_bIsFlashing)
	{
		RECT rFlash;
		rFlash.left = 0;
		rFlash.top = 0;
		rFlash.right = rFlash.left + CGame::GetInstance()->GetScreenWidth();
		rFlash.bottom = rFlash.top + CGame::GetInstance()->GetScreenHeight();
		CSGD_Direct3D::GetInstance()->GetSprite()->Flush();

		CSGD_Direct3D::GetInstance()->DrawRect(rFlash, 255, 255, 255);
	}

	//CSGD_Direct3D::GetInstance()->DrawRect(drawRect, 255, 0, 0);
}

RECT CPlayer::GetCollisionRect(void)
{
	RECT rect;
	rect.left = long(GetPosX());
	rect.top = long(GetPosY());
	rect.right = rect.left + GetWidth();
	rect.bottom = rect.top + GetHeight();

	return rect;
}

bool CPlayer::CheckCollisions(IBaseInterface* IBase)
{
	if(IBase->GetType() == OBJ_FIREWALL)
	{
		RECT temp;
		CFirewall* fire = (CFirewall*)IBase;
		RECT curtile = fire->GetCollisionRect();
		RECT obj = this->GetRect();
		if(fire->isitblocking())
		{
			if(IntersectRect(&temp, &obj, &curtile))
			{
				RECT player = this->GetRect();
				RECT wall = fire->GetCollisionRect();
				int wid = temp.right - temp.left;
				int het = temp.bottom - temp.top;

				if(wid > het)
				{
					if(obj.bottom > curtile.top && obj.top < curtile.top)
					{
						SetPosY(GetPosY() - (obj.bottom - curtile.top));
						SetVelY(0.0f);
					}
					if(obj.top < curtile.bottom && obj.bottom > curtile.bottom)
					{
						SetPosY(GetPosY() - (obj.top - curtile.bottom));
						SetVelY(0.0f);
					}

				}
				else if(het > wid)
				{
					if(obj.right > curtile.left && obj.left < curtile.left && GetVelX() != 0)
					{
						SetPosX(GetPosX() - (obj.right - curtile.left));
						SetVelX(0.0f);
					}

					if(obj.left < curtile.right && obj.right > curtile.right && GetVelX() != 0)
					{
						SetPosX(GetPosX() - (obj.left - curtile.right));
						SetVelX(0.0f);
					}


				}
			}
		}
	}

	if(IBase->GetType() == OBJ_WORM)
	{
		RECT tempr;
		CWorm* worm = (CWorm*)IBase;
		if(IntersectRect(&tempr, &this->GetRect(), &worm->GetCollisionRect()))
		{
			sethealth(gethealth() - worm->GetDamage());
			m_bIsFlashing = true;
			if(CCyberSpaceState::GetInstance()->GetHealth() - (256.0f*0.05f) > 0)
				CCyberSpaceState::GetInstance()->SetHealth(CCyberSpaceState::GetInstance()->GetHealth() - (256*0.05f));
			else
				CCyberSpaceState::GetInstance()->SetHealth(0.0f);

			CSGP_EventSystem::GetInstance()->SendEvent("enemy.death", worm);
			return true;
		}
	}

	if(IBase->GetType() == OBJ_SPIDER)
	{
		RECT tempr;
		CSpider* spid = (CSpider*)IBase;
		if(IntersectRect(&tempr, &this->GetRect(), &spid->GetCollisionRect()))
		{
			spid->SetPosX(spid->GetPosX() - spid->GetVelX());
			spid->SetPosY(spid->GetPosY() - spid->GetVelY());
			spid->setstop(true);
			sethealth(gethealth() - spid->GetDamage());
			if(CCyberSpaceState::GetInstance()->GetHealth() - (256.0f*0.05f) > 0)
				CCyberSpaceState::GetInstance()->SetHealth(CCyberSpaceState::GetInstance()->GetHealth() - (256*0.05f));
			else
				CCyberSpaceState::GetInstance()->SetHealth(0.0f);
			return true;
		}
	}
	if(IBase->GetType() == OBJ_PISTOL_BULLET)
	{
		CPistolBullet* tempb = (CPistolBullet*) IBase;
		if(tempb->GetBulletType() == CPistolBullet::BLT_ENEMY)
		{
			RECT tempr;
			if(IntersectRect(&tempr, &this->GetCollisionRect(), &tempb->GetCollisionRect()))
			{
				sethealth(gethealth() - 5);
				if(CCyberSpaceState::GetInstance()->GetHealth() - (256.0f*0.05f) > 0)
					CCyberSpaceState::GetInstance()->SetHealth(CCyberSpaceState::GetInstance()->GetHealth() - (256*0.05f));
				else
					CCyberSpaceState::GetInstance()->SetHealth(0.0f);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyPlayerBulletMessage(tempb));
				return true;
			}
		}
	}
	if(IBase->GetType() == CBase::OBJ_PICKUP)
	{
		CDrop* pDrop = (CDrop*)IBase;
		RECT pRect;
		if(pDrop->GetDropType() == CDrop::PISTOL)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				if(CCyberSpaceState::GetInstance()->GetCurrentWeapon() != CCyberSpaceState::PISTOL)
				{
					// Show notification text
					CCyberSpaceState::GetInstance()->SetPistolFlag(true);
				}

				SetPistolAmmo(GetPistolAmmo() + 10);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
			
		}
		else if(pDrop->GetDropType() == CDrop::SHOTGUN)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				if(CCyberSpaceState::GetInstance()->GetCurrentWeapon() != CCyberSpaceState::SHOTGUN)
				{
					// Show notification text
					CCyberSpaceState::GetInstance()->SetShotFlag(true);
				}

				SetShotgunAmmo(GetShotgunAmmo() + 10);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		else if(pDrop->GetDropType() == CDrop::ROCKET)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				if(CCyberSpaceState::GetInstance()->GetCurrentWeapon() != CCyberSpaceState::ROCKETS)
				{
					// Show notification text
					CCyberSpaceState::GetInstance()->SetRocketFlag(true);
				}

				SetRocketAmmo(GetRocketAmmo() + 10);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		else if(pDrop->GetDropType() == CDrop::HEALTH)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				if(CCyberSpaceState::GetInstance()->GetHealth() < 256)//CCyberSpaceState::GetInstance()->GetMaxHealth())//health < MaxHealth) && )
				{
					if( CCyberSpaceState::GetInstance()->GetHealth() + (256*0.1f) <= (CCyberSpaceState::GetInstance()->GetMaxHealth()))  //gethealth() + 10 < MaxHealth)&& ()
					{
						//sethealth(gethealth() + 10);
						CCyberSpaceState::GetInstance()->SetHealth(CCyberSpaceState::GetInstance()->GetHealth() + (256*0.1f));
					}
					else
						CCyberSpaceState::GetInstance()->SetHealth(CCyberSpaceState::GetInstance()->GetMaxHealth());

				}
				else //if (CCyberSpaceState::GetInstance()->GetHealth() >= CCyberSpaceState::GetInstance()->GetMaxHealth())//health >= MaxHealth && 
				{
						CCyberSpaceState::GetInstance()->SetHealth(CCyberSpaceState::GetInstance()->GetMaxHealth());
					
					//sethealth(MaxHealth);
				}
				
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		else if(pDrop->GetDropType() == CDrop::FW_GRENADE)
		{
			
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				SetFwGrenades(GetFwGrenades() + 1);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		else if(pDrop->GetDropType() == CDrop::SPEED)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				// Set the speed upgrade to be active
				CPlayer::GetInstance()->SetSpeedActive(true);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		
		else if(pDrop->GetDropType() == CDrop::FIRE_RATE)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				CPlayer::GetInstance()->SetFRActive(true);
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		else if(pDrop->GetDropType() == CDrop::MONEY)
		{
			if(IntersectRect(&pRect, &GetCollisionRect(), &pDrop->GetCollisionRect()))
			{
				money += 10;
				CSGP_MessageSystem::GetInstance()->SendMessageA(new CDestroyDropMessage(pDrop));
				return true;
			}
		}
		else

			return false;
	}
	return false;
}

int CPlayer::gethealth()
{
	return this->health;
}
void CPlayer::sethealth(int h)
{
	this->health = h;
}